/**
 *  Copyright 2011 Marco Berri - marcoberri@gmail.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
 **/
package com.mbfasttrack.service;

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.mbfasttrack.model.Group;
import com.mbfasttrack.model.Hardware;
import com.mbfasttrack.model.Media;
import com.mbfasttrack.model.MetaData;
import com.mbfasttrack.model.Track;
import com.mbfasttrack.model.User;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;
import imageUtil.Image;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.WebUtils;

/**
 * @author Marco Berri marcoberri@gmail.com http://tecnicume.blogspot.com
 */
@Service("MediaService")
@Transactional
public class MediaService extends Base {

    /**
     * 
     * @param media
     * @return
     */
    public Media add(Media media) {

        try {

            String newFileName;
            GridFSInputFile gfsFile = null;
            GridFS gfsPhoto = new GridFS(mongoTemplate.getDb(), "FileMedia");

            File tmp_dir = WebUtils.getTempDir(this.context);
            File filetemp = null;
            //è un file che arriva dalla multopart

            if (media.getMultipartfile() != null) {

                newFileName = media.getMultipartfile().getOriginalFilename().toLowerCase();
                gfsFile = gfsPhoto.createFile(media.getMultipartfile().getInputStream());
                gfsFile.setContentType(media.getMultipartfile().getContentType());
                filetemp = new File(tmp_dir + "/" + newFileName);

                media.getMultipartfile().transferTo(filetemp);


            } else {
                log.fatal("Media file is null");
                return null;
            }

            gfsFile.setFilename(newFileName);
            gfsFile.save();
            gfsFile.getId();

            List<MetaData> metas = new ArrayList<MetaData>();


            if (gfsFile.getContentType().equalsIgnoreCase("image/jpeg")
                    || gfsFile.getContentType().equalsIgnoreCase("image/jpg")) {
                //estraggo i dati exifs

                Metadata metadata = ImageMetadataReader.readMetadata(filetemp);

                for (Directory directory : metadata.getDirectories()) {
                    for (Tag tag : directory.getTags()) {
                        MetaData m = new MetaData();
                        m.setDirectory(tag.getDirectoryName());
                        m.setName(tag.getTagName());
                        m.setType(tag.getTagType());
                        m.setTypeHex(tag.getTagTypeHex());
                        m.setDescription(tag.getDescription());
                        metas.add(m);
                    }
                }
                media.setMetadata(metas);
            }

            media.setFileId(gfsFile.getId());

            media.setObjtype(media.getObjtype().toLowerCase());
            media = mediaRepository.save(media);


            //aggancio il media all'object
            media = addToObject(media);

            if (filetemp != null && filetemp.exists()) {
                filetemp.delete();
            }


            return media;

        } catch (Exception e) {
            System.err.println(e.getMessage());
            log.fatal(e);
            return null;
        }


    }

    /**
     * 
     * @param media
     * @return
     */
    public Media addTrackMap(Media media) {

        try {

            System.err.println("start addTrackMap to media:" + media);

            String newFileName;
            GridFSInputFile gfsFile = null;
            GridFS gfsPhoto = new GridFS(mongoTemplate.getDb(), "FileMedia");


            if (media.getFile() == null) {
                return null;
            }


            newFileName = media.getFile().toString();
            gfsFile = gfsPhoto.createFile(media.getFile());
            gfsFile.setContentType("image/png");

            File filetemp = media.getFile();
            gfsFile.setFilename(newFileName);
            gfsFile.save();

            System.err.println("start addTrackMap filetemp :" + filetemp);


            media.setFileId(gfsFile.getId());
            media.setType("staticmap");
            media = mediaRepository.save(media);

            //aggancio il media all'object
            media = addToObject(media);

            if (filetemp != null && filetemp.exists()) {
                filetemp.delete();

            }

            System.err.println("start addTrackMap Complete");
            return media;

        } catch (Exception e) {
            System.err.println(e.getMessage());
            log.fatal(e);
            return null;
        }


    }

    /**
     * 
     * @param media
     * @return
     */
    public Media addToObject(Media media) {

        if (media.getObjtype().equalsIgnoreCase("track")) {
            Track t = trackRepository.findOne(media.getObjid());
            if (t != null) {
                t.addMedia(media);
            } else {
                log.fatal("Track not found :" + media.getObjid());
                System.err.println("Track not found :" + media.getObjid());
            }

            trackRepository.save(t);

        } else if (media.getObjtype().equalsIgnoreCase("group")) {
            Group g = groupRepository.findOne(media.getObjid());
            if (g != null) {
                g.addMedia(media);
            } else {
                log.fatal("Group not found :" + media.getObjid());
                System.err.println("Group not found :" + media.getObjid());
            }

            groupRepository.save(g);

        } else if (media.getObjtype().equalsIgnoreCase("hardware")) {
            Hardware h = hardwareRepository.findOne(media.getObjid());
            if (h != null) {
                h.addMedia(media);
            } else {
                log.fatal("Hardware not found :" + media.getObjid());
                System.err.println("Hardware not found :" + media.getObjid());
            }

            hardwareRepository.save(h);

        } else if (media.getObjtype().equalsIgnoreCase("user")) {
            User u = userRepository.findOne(media.getObjid());
            if (u != null) {
                u.addMedia(media);
            } else {
                log.fatal("User not found :" + media.getObjid());
                System.err.println("User not found :" + media.getObjid());
            }

            userRepository.save(u);


        } else {
            return null;
        }


        return media;


    }

    /**
     * 
     * @param media 
     * @param username
     * @return
     */
    public Media add(Media media, String username) {
        media.setUser(userRepository.findOneByUsername(username));
        return this.add(media);
    }

    /**
     * 
     * @param id
     * @return
     */
    public GridFSDBFile getFile(ObjectId id) {
        GridFS gfsPhoto = new GridFS(mongoTemplate.getDb(), "FileMedia");

        return gfsPhoto.findOne(id);

    }

    /**
     * 
     * @param md5_file
     * @return
     */
    public File getCacheFile(String md5_file, String type) {


        File f = new File(WebUtils.getTempDir(this.context) + "/" + type + "/" + md5_file);

        if (f.exists()) {
            return f;
        }

        return null;
    }

    /**
     * 
     * @param md5_file
     * @param type 
     * @param image 
     * @param extension 
     * @return
     * @throws IOException
     */
    public File putCacheFile(String md5_file, String type, Image image, String extension) throws IOException {
        File dir = new File(WebUtils.getTempDir(this.context) + "/" + type + "/");
        try {
            org.apache.commons.io.FileUtils.forceMkdir(dir);
        } catch (Exception e) {
            System.err.print(e);
        }

        File f = new File(WebUtils.getTempDir(this.context) + "/" + type + "/" + md5_file);

        image.writeToFile(f, extension);

        return f;

    }
}
